package com.hdd.utils.wx;


import com.alibaba.fastjson.JSONObject;
import com.boot.gateway.model.actionRecord.VisitTrend;
import com.hdd.biz.member.entity.Member;
import com.hdd.biz.member.service.MemberService;
import com.hdd.biz.task.WxMiniProgramFlushAccessTokenJob;
import com.hdd.config.Constant;
import com.hdd.utils.DateUtil;
import com.hdd.utils.JsonUtil;
import com.hdd.utils.UUIDGenerator;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.UploadManager;
import com.qiniu.util.Auth;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.imageio.stream.FileImageOutputStream;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.text.DecimalFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author ;xuhu
 * @Description:
 * @Date: 2020-11-18 13:29
 **/
@Component
public class WxMiniProgramUtil {

    @Autowired
    private WxMiniProgramFlushAccessTokenJob wxAccessToken;

    @Autowired
    private MemberService memberService;

    @Value("${wx.miniprogram_state}")
    private String miniprogramState;

    @Value("${subscribeUrl}")
    private String subscribeUrl;

    @Value("${hddIndex}")
    private String hddIndex;

    //打赏推送
    private static final String REWARD_TEMPLATE_ID = "HfOayaPYKixW4q7gQ06nOYMO748yh3-tJ4zAMkr9pM0";
    //提现推送
    private static final String WITHDRAWAL_TEMPLATE_ID = "PUqejm9-WLtNj7bkSvmGw7UgxNQvh1qoVDPiu__uk08";

    /**
     * 获取小程序码
     *
     * @param scene 必传，最大32个可见字符，只支持数字，大小写英文以及部分特殊字符：!#$&'()*+,/:;=?@-._~，
     *              其它字符请自行编码为合法字符（因不支持%，中文无法使用 urlencode 处理，请使用其他编码方式）
     * @param page  非必传，必须是已经发布的小程序存在的页面（否则报错），例如 pages/index/index, 根路径前不要填加 /,不能携带参数（参数请放在scene字段里），
     *              如果不填写这个字段，默认跳主页面
     * @return
     */
    public byte[] getUnlimited(String scene, String page){
        long start = System.currentTimeMillis();
        String url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=";
        Map<String, Object> map = new HashMap<>();
        map.put("page", page);
        map.put("width", 280);
        map.put("scene", scene);
        map.put("is_hyaline", true);
        map.put("auto_color", true);

        wxPost(url + wxAccessToken.getAccessToken(),JsonUtil.toJsonString(map),null);

        byte[] bytes = post(url + wxAccessToken.getAccessToken(), JsonUtil.toJsonString(map));

        if (bytes == null || bytes.length == 0) {
            //可能是AccessToken 过期或无效，刷新重试
            bytes = post(url + wxAccessToken.getNewAccessToken(), JsonUtil.toJsonString(map));
        } else if (bytes.length < 200) {
            Map<String, Object> toMap = JsonUtil.toMap(new String(bytes));
            if ("40001".equals(toMap.get("errcode"))) {
                //可能是AccessToken 过期或无效，刷新重试
                bytes = post(url + wxAccessToken.getNewAccessToken(), JsonUtil.toJsonString(map));
            }
        }
        long end = System.currentTimeMillis();
        System.out.println("小程序码：" + (end - start));

        return bytes;
    }


    private Auth auth = null;
    private Configuration configuration = new Configuration();

    public String getUnlimitedUrl(String scene, String page){
        String url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token="+wxAccessToken.getAccessToken();
        Map<String, Object> map = new HashMap<>();
        map.put("page", page);
        map.put("width", 280);
        map.put("scene", scene);
        Document document = null;
        System.out.println(JsonUtil.toJsonString(map).length());
        System.out.println(JsonUtil.toJsonString(map));
        try {
            document  = Jsoup.connect(url).timeout(40000).ignoreContentType(true)
                    .header("Content-type","application/json; charset=utf-8")
                    .requestBody(JsonUtil.toJsonString(map)).post();

        }catch (Exception e){
            e.printStackTrace();
        }

        return url;
    }


    //第二步写入图片
    public  void wxPost(String uri, String paramJson, String fileName) {
        try {
            URL url = new URL(uri);
            HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
            httpURLConnection.setRequestMethod("POST");// 提交模式
            // conn.setConnectTimeout(10000);//连接超时 单位毫秒
            // conn.setReadTimeout(2000);//读取超时 单位毫秒
            // 发送POST请求必须设置如下两行
            httpURLConnection.setDoOutput(true);
            httpURLConnection.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            PrintWriter printWriter = new PrintWriter(httpURLConnection.getOutputStream());
            printWriter.write(paramJson);
            // flush输出流的缓冲
            printWriter.flush();
            // 开始获取数据
            BufferedInputStream bis = new BufferedInputStream(httpURLConnection.getInputStream());
            System.out.println(bis);
            File file = new File("d:/122222.png");
            OutputStream os = new FileOutputStream(file);
            int len;
            byte[] arr = new byte[1024];
            while ((len = bis.read(arr)) != -1) {
                os.write(arr, 0, len);
                os.flush();
            }
            os.close();
            bis.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 获取用户访问小程序数据日趋势
     *
     * @param beginDate 开始日期，为自然月第一天。格式为 yyyymmdd
     * @param endDate   结束日期，为自s然月最后一天，限定查询一个月的数据。格式为 yyyymmdd
     * @return
     */
    public List<VisitTrend> getDailyVisitTrend(String beginDate,String endDate){
        String url = "https://api.weixin.qq.com/datacube/getweanalysisappiddailyvisittrend?access_token=";

        return getVisitTrend(url, beginDate, endDate);
    }

    /**
     * 获取用户访问小程序数据月趋势(能查询到的最新数据为上一个自然月的数据)
     *
     * @param beginDate 开始日期，为自然月第一天。格式为 yyyymmdd
     * @param endDate   结束日期，为自然月最后一天，限定查询一个月的数据。格式为 yyyymmdd
     * @return
     */
    public List<VisitTrend> getMonthlyVisitTrend(String beginDate,String endDate){
        String url = "https://api.weixin.qq.com/datacube/getweanalysisappidmonthlyvisittrend?access_token=";

        return getVisitTrend(url, beginDate, endDate);
    }

    /**
     * 获取用户访问小程序数据周趋势
     *
     * @param beginDate 开始日期，为周一日期。格式为 yyyymmdd
     * @param endDate   结束日期，为周日日期，限定查询一周数据。格式为 yyyymmdd
     * @return
     */
    public List<VisitTrend> getWeeklyVisitTrend(String beginDate,String endDate){
        String url = "https://api.weixin.qq.com/datacube/getweanalysisappidweeklyvisittrend?access_token=";

        return getVisitTrend(url, beginDate, endDate);
    }

    /**
     * 发送订阅消息
     *
     * @param sendUserId   接收者的 id（被赞赏的用户）
     * @param paintingName 作品名称
     * @param userNickname 打赏用户的昵称
     * @param amount       打赏金额
     */
    public void sendRewardMessage(String sendUserId, String paintingName, String userNickname, double amount,String worksId) {
        String url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=";

        Member userInfo = memberService.findMemberByUid(sendUserId);

        Map<String, Object> data = new HashMap<>();

        //打赏作品
        Map<String, Object> value1 = new HashMap<>(4);
        paintingName = EmojiConvertUtil.recoveryEmoji(paintingName);
        value1.put("value", "《" + paintingName + "》");
        data.put("thing1", value1);

        //赞赏金额
        Map<String, Object> value2 = new HashMap<>(4);
        value2.put("value", String.format("%.2f", amount));
        data.put("amount2", value2);

        //赞赏人
        Map<String, Object> value3 = new HashMap<>(4);
        value3.put("value", userNickname);
        data.put("thing3", value3);

        //打赏时间
        Map<String, Object> value4 = new HashMap<>(4);
        value4.put("value", DateUtil.datetimeToString(new Date()));
        data.put("time4", value4);

        Map<String, Object> params = new HashMap<>();
        params.put("touser", userInfo.getXcxOpenid());
        params.put("template_id", REWARD_TEMPLATE_ID);
       // params.put("page", subscribeUrl + "?userId=" + sendUserId);
        params.put("page", "pages/mine/paintList?targetId="+sendUserId+"&worksId="+worksId+"&from=share"); //跳转页面
        params.put("miniprogram_state", miniprogramState);
        params.put("data", data);

        String s = doPost(url, params);

        System.out.println(s);
    }


    /**
     * 发送提现消息
     * @param sendUserId
     * @param name
     * @param account
     * @param amount
     */
    public void sendWithdrawalMessage(String sendUserId, String name, String remk, double amount,String zt) {
        String url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=";

        Member userInfo = memberService.findMemberByUid(sendUserId);
        Map<String, Object> data = new HashMap<>();
        //用户昵称
        Map<String, Object> value1 = new HashMap<>(4);
        name = EmojiConvertUtil.recoveryEmoji(name);
        value1.put("value", "" + name + "");
        data.put("name1", value1);

        //提现金额金额
        Map<String, Object> value2 = new HashMap<>(4);
        value2.put("value", String.format("%.2f", amount));
        data.put("amount3", value2);
        //提现结果
        Map<String, Object> value3 = new HashMap<>(4);
        value3.put("value", zt);
        data.put("phrase4", value3);
        //备注
        Map<String, Object> value4 = new HashMap<>(4);
        value4.put("value", remk);
        data.put("thing5", value4);

        //提现时间
        Map<String, Object> value0 = new HashMap<>(4);
        value0.put("value", DateUtil.datetimeToString(new Date()));
        data.put("date2", value0);
        //提现状态
        Map<String, Object> value5 = new HashMap<>(4);
        value5.put("value", zt);
        data.put("phrase6", value5);
        Map<String, Object> params = new HashMap<>();
        params.put("touser", userInfo.getXcxOpenid());
        params.put("template_id", WITHDRAWAL_TEMPLATE_ID);
        // params.put("page", subscribeUrl + "?userId=" + sendUserId);
        params.put("page", hddIndex);
        params.put("miniprogram_state", miniprogramState);
        params.put("data", data);
        String s = doPost(url, params);
        System.out.println(s);

    }


    private List<VisitTrend> getVisitTrend(String url, String beginDate, String endDate) {
        Map<String, Object> map = new HashMap<>();
        map.put("begin_date", beginDate);
        map.put("end_date", endDate);
        String json = doPost(url, map);
        Map<String, Object> objectMap = JsonUtil.toMap(json);

        return JsonUtil.parseList(objectMap.get("list").toString(), VisitTrend.class);
    }

    private  String doPost(String url,Map<String, Object> map){
        String json = "";
        byte[] bytes = post(url + wxAccessToken.getAccessToken(), JsonUtil.toJsonString(map));
        if (bytes == null || bytes.length == 0) {
            //可能是AccessToken 过期或无效，刷新重试
            bytes = post(url + wxAccessToken.getNewAccessToken(), JsonUtil.toJsonString(map));
            json = new String(bytes, StandardCharsets.UTF_8);
        }else {
            json = new String(bytes, StandardCharsets.UTF_8);
            if (json.contains("40001")) {
                //可能是AccessToken 过期或无效，刷新重试
                bytes = post(url + wxAccessToken.getNewAccessToken(), JsonUtil.toJsonString(map));
                json = new String(bytes, StandardCharsets.UTF_8);
            }
        }
        return json;
    }



    private byte[] post(String url, String json) {
        byte[] data = null;
        // 创建默认的httpClient实例.
        CloseableHttpClient httpclient = HttpClients.createDefault();
        // 创建httppost
        HttpPost httppost = new HttpPost(url);
        httppost.addHeader("Content-type", "application/json; charset=utf-8");
        httppost.setHeader("Accept", "application/json");
        CloseableHttpResponse response = null;
        try {
            StringEntity s = new StringEntity(json, Charset.forName("UTF-8"));
            s.setContentEncoding("UTF-8");
            httppost.setEntity(s);
            response = httpclient.execute(httppost);
            // 获取相应实体
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                InputStream inputStream = entity.getContent();
                data = readInputStream(inputStream);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 关闭连接,释放资源
            try {
                if (response != null) {
                    response.close();
                }
                httpclient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return data;
    }

    /**
     * 将流 保存为数据数组
     *
     * @param inStream
     * @return
     * @throws Exception
     */
    private byte[] readInputStream(InputStream inStream) throws Exception {
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        // 创建一个Buffer字符串
        byte[] buffer = new byte[1024];
        // 每次读取的字符串长度，如果为-1，代表全部读取完毕
        int len = 0;
        // 使用一个输入流从buffer里把数据读取出来
        while ((len = inStream.read(buffer)) != -1) {
            // 用输出流往buffer里写入数据，中间参数代表从哪个位置开始读，len代表读取的长度
            outStream.write(buffer, 0, len);
        }
        // 关闭输入流
        inStream.close();
        // 把outStream里的数据写入内存
        byte[] bytes = outStream.toByteArray();
        outStream.close();
        return bytes;
    }
}